# coding=utf-8
import time
from function_utils import Global, Common, PsUtil, TableRender


def calculate_disk(last, curr):
    """
    :rrqm/s   : The number of read requests merged per second that were queued to the device.
               (rd_merges[1] - rd_merges[0])
    :wrqm/s   :
    :r/s      : The number of read requests that were issued to the device per second.
               (rd_ios[1] - rd_ios[0])
    :w/s      :
    :rkB/s    : The number of kilobytes read from the device per second.
                (rd_sectors[1] - rd_sectors[0]) * sector_size
    :wkB/s    :
    :avgrq-sz : The average size **in sectors** of the requests that were issued to the device.
                (( rd_sectors[1] - rd_sectors[0] ) + ( wr_sectors[1] - wr_sectors[0] )) / (rd_ios[1] - rd_ios[0]) + (wr_ios[1] - wr_ios[0])
    :avgqu-sz : The average queue length of the requests that were issued to the device.
                (rq_ticks[1] - rq_ticks[0]) / 1000
    :await    : The average time (in milliseconds) for I/O requests issued to the  device  to  be  served
                (( rd_ticks[1] - rd_ticks[0] ) + ( wr_ticks[1] - wr_ticks[0] )) / (rd_ios[1] - rd_ios[0]) + (wr_ios[1] - wr_ios[0])
    :svctm    : The average service time (in milliseconds) for I/O requests that were issued to the device.
                util / (rd_ios[1] - rd_ios[0]) + (wr_ios[1] - wr_ios[0])
    :util     : Percentage  of  CPU time during which I/O requests were issued to the device
                (tot_ticks[1] - tot_ticks[0]) / 1000 * 100
    """
    SECTOR_SIZE = 512

    def diff(field):
        return (curr[field] - last[field]) / (curr["ts"] - last["ts"])

    _r_ios = diff('r_ios')
    _w_ios = diff('w_ios')
    if _r_ios + _w_ios > 0:
        _avgrq_sz = (diff('r_sec') + diff('w_sec')) / (diff('r_ios') + diff('w_ios'))
        _await = (diff('r_ticks') + diff('w_ticks')) / (diff('r_ios') + diff('w_ios'))
        _svctm = diff('tot_ticks') / (diff('r_ios') + diff('w_ios'))
    else:
        _avgrq_sz = 0
        _await = 0
        _svctm = 0

    stat = (
        curr['dev'],
        '%.1f' % diff('r_merges'),
        '%.1f' % diff('w_merges'),
        '%.1f' % _r_ios,
        '%.1f' % _w_ios,
        '%.1f' % (diff('r_sec') * SECTOR_SIZE / 1024),
        '%.1f' % (diff('w_sec') * SECTOR_SIZE / 1024),
        '%.1f' % (diff('rq_ticks') / 1000),
        '%.1f' % _avgrq_sz,
        '%.1f' % _await,
        '%.1f' % _svctm,
        '%.1f' % (diff('tot_ticks') / 10)
    )
    return stat


def disk_info(interval=2):
    cmd = '''
    export LC_ALL=C
    df -h
    unset LC_ALL
    '''
    out = Common.execute_cmd(cmd)[1]
    info = 'Device|rrqm/s|wrqm/s|r/s|w/s|rkB/s|wkB/s|avqqu-sz|avgrq-sz|await|svctm|%util'
    last = PsUtil.diskstats()
    time.sleep(interval)
    curr = PsUtil.diskstats()
    for dev, stat in last.items():
        if dev in curr:
            info = '%s\n%s' % (info, '|'.join(calculate_disk(stat, curr[dev])))
    info = info.strip()
    out = '''
<BLUE> ##### > Disk IO:
%s

<BLUE> ##### > Disk Partition:
%s
    ''' % (TableRender(info), out)
    return out


def write_widgets_value(value):
    data = [{"MultiInfoText": value},
            {}
            ]
    Global.values_write(data)
    Global.report_info(100)


def main():
    write_widgets_value(disk_info())


if __name__ == '__main__':
    main()
